/*
 * Copyright (C) 2019 ByteDance Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bytedance.scene;

import com.bytedance.scene.interfaces.ActivityResultCallback;
import com.bytedance.scene.interfaces.PermissionResultCallback;
import com.bytedance.scene.navigation.ConfigurationChangedListener;
import com.bytedance.scene.utlity.ThreadUtility;
import com.bytedance.scene.utlity.Utility;
import ohos.aafwk.ability.*;
import ohos.aafwk.ability.fraction.Fraction;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.IntentParams;
import ohos.global.configuration.Configuration;

import java.util.*;

/**
 * @hide
 **/
public class SceneActivityCompatibilityLayerFragment extends Fraction {
    public interface OnActivityCreatedCallback {
        void onActivityCreated();
    }

    private final Map<Integer, ActivityResultCallback> mResultCallbackMap = new HashMap();
    private final Map<Integer, PermissionResultCallback> mPermissionResultCallbackMap = new HashMap<>();
    private final List<ConfigurationChangedListener> mConfigurationChangedListenerList = new ArrayList<>();
    private final Set<OnActivityCreatedCallback> mOnActivityCreatedCallbackSet = new HashSet<>();

    static SceneActivityCompatibilityLayerFragment newIntent() {
        return new SceneActivityCompatibilityLayerFragment();
    }

    void addOnActivityCreatedCallback(OnActivityCreatedCallback callback) {
        this.mOnActivityCreatedCallbackSet.add(callback);
    }

    void removeOnActivityCreatedCallback(OnActivityCreatedCallback callback) {
        this.mOnActivityCreatedCallbackSet.remove(callback);
    }

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        Set<OnActivityCreatedCallback> copy = new HashSet<>(this.mOnActivityCreatedCallbackSet);
        for (OnActivityCreatedCallback callback : copy) {
            callback.onActivityCreated();
        }
    }


    void startActivityForResultByScene(final ILifecycle lifecycleOwner, Intent intent,
                                       final int requestCode, ActivityResultCallback resultCallback) {
        if (!isCurrentStatusValid(lifecycleOwner)) {
            return;
        }

        if (requestCode < 0) {
            getFractionAbility().startAbility(intent);
            return;
        }
        mResultCallbackMap.put(requestCode, resultCallback);
        getFractionAbility().startAbilityForResult(intent, requestCode);
        lifecycleOwner.getLifecycle().addObserver((LifecycleStateObserver) (event, intent1) -> {
            if (Lifecycle.Event.ON_STOP.name().equals(event.name())) {
                lifecycleOwner.getLifecycle().removeObserver((ILifecycleObserver) this);
                mResultCallbackMap.remove(requestCode);
            }
        });

    }

    void startActivityForResultByScene(final ILifecycle lifecycleOwner, Intent intent,
                                       final int requestCode, IntentParams options,
                                       ActivityResultCallback resultCallback) {
        if (!isCurrentStatusValid(lifecycleOwner)) {
            return;
        }

        if (requestCode < 0) {
            startAbility(intent,requestCode);
            return;
        }
        mResultCallbackMap.put(requestCode, resultCallback);
        getFractionAbility().startAbilityForResult(intent, requestCode);
        lifecycleOwner.getLifecycle().addObserver((LifecycleStateObserver) (event, intent1) -> {
            if (Lifecycle.Event.ON_STOP.name().equals(event.name())) {
                lifecycleOwner.getLifecycle().removeObserver((ILifecycleObserver) this);
                mResultCallbackMap.remove(requestCode);
            }
        });
    }

    void requestPermissionsByScene(final ILifecycle lifecycleOwner, String[] permissions,
                                   final int requestCode, final PermissionResultCallback resultCallback) {
        if (!isCurrentStatusValid(lifecycleOwner)) {
            return;
        }
        mPermissionResultCallbackMap.put(requestCode, resultCallback);
        requestPermissionsFromUser(permissions, requestCode);
        lifecycleOwner.getLifecycle().addObserver((LifecycleStateObserver) (event, intent1) -> {
            if (Lifecycle.Event.ON_STOP.toString().equals(event.name())) {
                lifecycleOwner.getLifecycle().removeObserver((ILifecycleObserver) this);
                mResultCallbackMap.remove(requestCode);
            }
        });
    }


    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        ActivityResultCallback callback = mResultCallbackMap.get(requestCode);
        if (callback != null) {
            callback.onResult(resultCode, data);
            mResultCallbackMap.remove(requestCode);
        }
    }

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        PermissionResultCallback callback = mPermissionResultCallbackMap.get(requestCode);
        if (callback != null) {
            callback.onResult(grantResults);
            mPermissionResultCallbackMap.remove(requestCode);
        }
    }

    private boolean isCurrentStatusValid(final ILifecycle lifecycleOwner) {
        ThreadUtility.checkUIThread();
        Ability activity = getFractionAbility();
        if (!Utility.isActivityStatusValid(activity)) {
            return false;
        }

        if (lifecycleOwner.getLifecycle().getLifecycleState() == Lifecycle.Event.ON_STOP) {
            // ignore
            return false;
        }
        return true;
    }

    void addConfigurationChangedListener(final ILifecycle lifecycleOwner,
                                         final ConfigurationChangedListener configurationChangedListener) {
        if (!isCurrentStatusValid(lifecycleOwner)) {
            return;
        }
        mConfigurationChangedListenerList.add(configurationChangedListener);
        lifecycleOwner.getLifecycle().addObserver(new LifecycleStateObserver() {
            @Override
            public void onStateChanged(Lifecycle.Event event, Intent intent) {
                if (Lifecycle.Event.ON_STOP.toString().equals(event.name())) {
                    lifecycleOwner.getLifecycle().removeObserver(this);
                    mConfigurationChangedListenerList.remove(configurationChangedListener);
                }
            }
        });
    }

    public void onConfigurationChanged(Configuration newConfig) {
        List<ConfigurationChangedListener> copy = new ArrayList<>(mConfigurationChangedListenerList);
        for (int i = copy.size() - 1; i >= 0; i--) {
            ConfigurationChangedListener listener = copy.get(i);
            if (listener != null) {
                listener.onConfigurationChanged(newConfig);
            }
        }
    }

}
